/**
 * @typedef {import('axios').AxiosRequestConfig} requestConfig 请求配置
 *
 * @typedef {[url: string, data?: any, config?: requestConfig]} requestArgs 请求参数
 */

import stringify from 'qs/lib/stringify'
import axios from 'axios'
import { ElMessage } from 'element-plus'
import { API_BASE } from './consts'

/**
 * 请求错误处理
 * @description 当接口响应结果不符合预期时，返回一个被拒绝的承诺
 * @param {{ statusCode: number, message: string, data: any }} param0 添加到`Error`实例的字段
 * @param {boolean} showMsg 是否显示错误消息提示
 */
const onReject = ({ statusCode, message, data }, showMsg = true) => {
  message = message || '发生未知异常'
  showMsg && ElMessage.error(message)
  const error = new Error(message)
  error.data = data
  error.statusCode = statusCode
  return Promise.reject(error)
}

/**
 * 获取下载的文件名
 * @param {string} content 响应头中的`content-disposition`字段
 */
const getFileName = content => {
  const arr = decodeURIComponent(content)
    .toLowerCase()
    .split(';')
    .pop()
    .split('=')
  return (arr[arr.indexOf('filename') + 1] || '')
    .split('/')
    .pop()
}

/**
 * 创建axios实例
 * @param {boolean?} isForm
 * @param {string?} baseURL
 */
const createInstance = (isForm, baseURL = API_BASE) => {
  const instance = axios.create()
  instance.defaults.baseURL = baseURL
  instance.defaults.withCredentials = true
  if (isForm) {
    instance.defaults.transformRequest = [_ => stringify(_)]
  }

  instance.interceptors.response.use(
    res => {
      const { data } = res
      if (data instanceof Blob) {
        data.name = getFileName(res.headers['content-disposition'])
      }
      return data
    },
    async e => {
      const res = e.response
      const { data, status } = res || {}
      const message = [
        status || '',
        JSON.stringify((data || {}).detail || data || e.message || '请求失败，请稍候重试')
      ].join(', ')
      return onReject({ message, data, statusCode: status })
    }
  )

  return instance
}

const formRequest = createInstance(true)

/** axios实例，用于处理ajax请求 */
export const request = createInstance()

/**
 * ajax post请求方法，用于传统的表单提交
 * @param {requestArgs} args
*/
export const post = (...args) => formRequest.post(...args)
